/*
Hello, World! example
June 11, 2015
Copyright (C) 2015 David Martinez
All rights reserved.
This code is the most basic barebones code for writing a program for Arduboy.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#pragma once

#include <SPI.h>
#include <Wire.h>
#include <EEPROM.h>
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"

#define DEBUG_JOYSTICK 0
#define USE_JOYSTICK 0

#define JOYSTICK_X A0
#define JOYSTICK_Y A1
#define JOYSTICK_BUTTON 7  

#define KEY_BUTTON_A 11  
#define KEY_BUTTON_B 12  
#define KEY_BUTTON_UP 2  
#define KEY_BUTTON_DOWN 4  
#define KEY_BUTTON_LEFT 5  
#define KEY_BUTTON_RIGHT 3  

  
#define LEFT_BUTTON _BV(5)
#define RIGHT_BUTTON _BV(6)
#define UP_BUTTON _BV(7)
#define DOWN_BUTTON _BV(4)
#define A_BUTTON _BV(3)
#define B_BUTTON _BV(2)

class ArduboyTunes {
public: 
  void tone(unsigned int frequency, unsigned long duration)
  {
    
  }
};

class ArduboyAudio {
  
};

#define OLED_RESET 4
class Arduboy : public Adafruit_SSD1306 {
public:
  Arduboy() :Adafruit_SSD1306(OLED_RESET), frameRate(1), frameTime(0), pressFrames(0), stateJoyStick(0) {
  }

  void drawBitmap
  (int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, 
   uint8_t color)
  {
    int16_t i, j, byteWidth = (w + 7) / 8;
  
    for(j=0; j<h; j++) {
      for(i=0; i<w; i++ ) {
        if((pgm_read_byte(bitmap + (j / 8) * w + i) & (1 << (j % 8))) != 0) {
          drawPixel(x+i, y+j, color);
        }
      }
    }
  }
  
  void start() {
    begin();
  }

  void initRandomSeed() {
    //FIXME:???
  }

  void begin() {
    // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
    Adafruit_SSD1306::begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
    // init done
    
    // Show image buffer on the display hardware.
    // Since the buffer is intialized with an Adafruit splashscreen
    // internally, this will display the splashscreen.
    display();
    delay(2000);
    fillScreen(BLACK);
    display();
    setTextColor(WHITE);

#if USE_JOYSTICK
    //joystick
#if DEBUG_JOYSTICK
    Serial.begin(9600);
#endif
    pinMode(JOYSTICK_BUTTON, INPUT_PULLUP);
#else
    pinMode(KEY_BUTTON_A, INPUT_PULLUP);
    pinMode(KEY_BUTTON_B, INPUT_PULLUP);
    pinMode(KEY_BUTTON_UP, INPUT_PULLUP);
    pinMode(KEY_BUTTON_DOWN, INPUT_PULLUP);
    pinMode(KEY_BUTTON_LEFT, INPUT_PULLUP);
    pinMode(KEY_BUTTON_RIGHT, INPUT_PULLUP);
#endif  
    frameTime = millis();
    pressFrames = 0;
  }

  volatile int frameRate;
  volatile uint32_t frameTime;
  volatile uint32_t pressFrames;
  volatile int stateJoyStick;
  void setFrameRate(int x) {
    frameRate = x;
  }

  bool nextFrame() {
#if USE_JOYSTICK
#if DEBUG_JOYSTICK
    Serial.print("X=");
    Serial.print(analogRead(JOYSTICK_X));
    Serial.print(",");
  
    Serial.print("Y=");
    Serial.print(analogRead(JOYSTICK_Y));
    Serial.print(",");
  
    Serial.print("BUTTON state = ");
    Serial.println(digitalRead(JOYSTICK_BUTTON));
#endif
    
    uint32_t cur_frameTime = millis();
    int32_t delta = cur_frameTime - frameTime;
    int32_t delta2 = cur_frameTime - pressFrames;

    if (delta2 > 100)
    {
      stateJoyStick = 0;
      int joystick_x = analogRead(JOYSTICK_X);
      int joystick_y = analogRead(JOYSTICK_Y);
      int joystick_button = digitalRead(JOYSTICK_BUTTON);
      if (joystick_x > 1000 && joystick_y < 200) {
        //A
        stateJoyStick |= A_BUTTON;
      } else if (joystick_x < 200) {
        //left
        stateJoyStick |= LEFT_BUTTON;
      } else if (joystick_x > 1000) {
        //right
        stateJoyStick |= RIGHT_BUTTON;
      } else if (joystick_y < 200) {
        //top
        stateJoyStick |= UP_BUTTON;
      } else if (joystick_y > 1000) {
        //down
        stateJoyStick |= DOWN_BUTTON;
      }
      if (joystick_button == 0) {
        //B
        stateJoyStick |= B_BUTTON;
      }
      if (stateJoyStick != 0) {
        pressFrames = cur_frameTime;
      }
    }
#else


   
    uint32_t cur_frameTime = millis();
    int32_t delta = cur_frameTime - frameTime;
    int32_t delta2 = cur_frameTime - pressFrames;

    if (delta2 > 100)
    {
      stateJoyStick = 0;
      int key_button_a = digitalRead(KEY_BUTTON_A);
      int key_button_b = digitalRead(KEY_BUTTON_B);
      int key_button_up = digitalRead(KEY_BUTTON_UP);
      int key_button_down = digitalRead(KEY_BUTTON_DOWN);
      int key_button_left = digitalRead(KEY_BUTTON_LEFT);
      int key_button_right = digitalRead(KEY_BUTTON_RIGHT);
      if (key_button_a == 0) {
        stateJoyStick |= A_BUTTON;
      }
      if (key_button_b == 0) {
        stateJoyStick |= B_BUTTON;
      }
      if (key_button_up == 0) {
        stateJoyStick |= UP_BUTTON;
      }
      if (key_button_down == 0) {
        stateJoyStick |= DOWN_BUTTON;
      }
      if (key_button_left == 0) {
        stateJoyStick |= LEFT_BUTTON;
      }
      if (key_button_right == 0) {
        stateJoyStick |= RIGHT_BUTTON;
      }
      if (stateJoyStick != 0) {
        pressFrames = cur_frameTime;
      }
    }
#endif
    
    
    if (delta < 0 || delta >  1000 / frameRate) {
      frameTime = cur_frameTime;
      return true;
    } else {
      //skip
      return false;
    }
  }

  void clear() {
    clearDisplay();
  }

  bool pressed(int x_) {
    bool result = ((stateJoyStick & x_) != 0);
    stateJoyStick &= ~x_;
    return result;
    //return false;
  }

  int getInput() {
    return stateJoyStick;
  }

  bool everyXFrames(int x)
  {
    //FIXME:
    return true;
  }


  ArduboyTunes tunes;
  ArduboyAudio audio;
};


//#define NUMFLAKES 10
//#define XPOS 0
//#define YPOS 1
//#define DELTAY 2

//#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
//#endif

//extern const unsigned char arduboy_logo[];
//arduboy.drawBitmap(20, 5, arduboy_logo, 88, 16, WHITE);
